package love.simbot.example.listen.listenServer;

import catcode.CatCodeUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.ktor.util.Hash;
import love.forte.simbot.api.message.MessageContent;
import love.forte.simbot.api.message.assists.Permissions;
import love.forte.simbot.api.message.containers.AccountInfo;
import love.forte.simbot.api.message.events.GroupAddRequest;
import love.forte.simbot.api.message.events.GroupMsg;
import love.forte.simbot.api.message.events.MessageGet;
import love.forte.simbot.api.message.results.GroupAdmin;
import love.forte.simbot.api.message.results.GroupFullInfo;
import love.forte.simbot.api.sender.Getter;
import love.forte.simbot.api.sender.Sender;
import love.forte.simbot.api.sender.Setter;
import love.simbot.example.constant.Constant;
import love.simbot.example.entity.Image.ImageData;
import love.simbot.example.entity.baidu.TranslationMapper;
import love.simbot.example.entity.baidu.TranslationResult;
import love.simbot.example.entity.bilibili.VideoData;
import love.simbot.example.entity.bilibili.VideoResult;
import love.simbot.example.entity.chatRobot.ChatRobot;
import love.simbot.example.entity.chatRobot.MoliChatRobot;
import love.simbot.example.entity.epidemic.LocationMessage;
import love.simbot.example.entity.wangyi.newSong.QQSongResult;
import love.simbot.example.entity.wangyi.newSong.WangYiSongResult;
import love.simbot.example.entity.wangyi.search.QQResult;
import love.simbot.example.entity.wangyi.search.SearchResult;
import love.simbot.example.utils.baidu.TransApi;
import love.simbot.example.utils.bilibili.BiliBiliUtils;
import love.simbot.example.utils.chatRobot.ChatRobotUtils;
import love.simbot.example.utils.chatRobot.RobotUtils;
import love.simbot.example.utils.epidemic.EpidemicHttpUtils;
import love.simbot.example.utils.image.ImageUtils;
import love.simbot.example.utils.wangyi.MusicUtils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.acl.Group;
import java.util.*;
import java.util.concurrent.*;

public abstract class GroupService {

    private static Properties config = new Properties();
    static {
        FileInputStream input = null;
        try {
            input = new FileInputStream("src\\main\\resources\\config.properties");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            config.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 核心线程数为30的定时任务的线程池
    public static  final ScheduledExecutorService schedule =
            Executors.newScheduledThreadPool(30);

    // 音乐表单
    public static final ConcurrentHashMap<Long, HashMap<Integer,Long>> musicList =
            new ConcurrentHashMap<>();


    // 指令集(这里不用指令集存储下上一次对下一次指令有影响的指令也可以使用监听器的优先级来搞定)
    public static final  ConcurrentHashMap<Long,String> codeMap =
            new ConcurrentHashMap<>();

    // 定时任务
    public static final ConcurrentHashMap<Long, ScheduledFuture> timeTaskMap =
            new ConcurrentHashMap<>();


    // 群权限的信息
    public static final ConcurrentHashMap<String,HashMap<String,Permissions>> groupPermission
            = new ConcurrentHashMap<>();

    public static final ConcurrentHashMap<Long,GroupAddRequest> groupAddRequestMap
            = new ConcurrentHashMap<>();

    // 群聊代言模式的集合
    public static final ConcurrentHashMap<String,String> groupRepresent
            = new ConcurrentHashMap<>();




    // 敏感词列表(这里使用Set集合是为了防止重复)
    public static final LinkedHashSet<String> badWords = new LinkedHashSet<>();

    // 关闭的功能(这里使用Set集合是为了防止重复)
    public static final HashMap<String,Set<Character>> closeMenu = new HashMap<>();


    // 视频集合
    public static final  ConcurrentHashMap<String,List<VideoData>> videoMap =
            new ConcurrentHashMap<>();





    // 百度翻译的调用
    public static void translationLanguage(String message,GroupMsg groupMsg, MessageGet getter, Sender sender){
        String[] params = message.split("^[A-Z] ");

        if(params == null || params.length < 2){
            sender.sendPrivateMsg(getter,"您的参数格式有问题哦！Miku Miku~~");
            return;
        }

        TransApi transApi = new TransApi(Constant.BaiDu_APPID,Constant.BaiDu_SECRETKEY);
        String transResult = transApi.getTransResult(params[1], "auto", "zh");

        if(transResult.contains("error_code")){
            sender.sendGroupMsg(groupMsg,"对不起,Miku现在还翻译不了！！！");
            return;
        }


        // 将翻译的Json串进行转换
        ObjectMapper om = new ObjectMapper();
        TranslationResult translationResult = null;
        try {
            translationResult  = om.readValue(transResult, TranslationResult.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        List<TranslationMapper> trans_result = translationResult.getTrans_result();

        StringBuffer buffer = new StringBuffer();
        for (TranslationMapper translationMapper : trans_result) {
            buffer.append(translationMapper.getSrc());
            buffer.append("：");
            buffer.append("\n");
            buffer.append(translationMapper.getDst());
        }

        // 翻译功能
        sender.sendGroupMsg(groupMsg, buffer.toString());

    }




    // 搜索音乐
    public static void searchMusic(String message,
                                   Sender sender,
                                   GroupMsg groupMsg,
                                   MessageGet getter)  {
        // 1.进行消息切割
        String[] params = message.split("^[A-Z] ");


        if(params == null || params.length < 2 || params.length > 2){
            sender.sendPrivateMsg(getter,"主人,您的输入方式有问题呢!");
            return;
        }

        SearchResult searchResult = MusicUtils.SearchMusic(params[1], 5);
        QQResult qqResult = null;
        try {
            qqResult = MusicUtils.getQQMusicInfo(params[1]);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        if (searchResult == null || qqResult == null){
            sender.sendPrivateMsg(getter,"对不起 Miku正在休息中~~ 请主人之后再操作~~");
            return;
        }

        StringBuffer buffer = new StringBuffer();

        HashMap<Integer,Long> ids = new HashMap<>();

        buffer.append("请选择要播放的歌曲:\n");
        // 网易音乐
        buffer.append("======== 网易音乐 ========\n");
        for (int i = 0; i < searchResult.getResult().getSongs().size(); i++) {
            buffer.append(i+1+". ");
            buffer.append(searchResult.getResult().getSongs().get(i).getName()+"\t");
            buffer.append(searchResult.getResult().getSongs().get(i).getArtists().get(0).getName()+"\n");
            ids.put(i+1,searchResult.getResult().getSongs().get(i).getId());
        }
        buffer.append("======== QQ音乐 ========\n");
        for (int i = 0; i < qqResult.getData().size() && i < 5; i++) {
            buffer.append(i+6+". ");
            buffer.append(qqResult.getData().get(i).getSong()+"\t");
            buffer.append(qqResult.getData().get(i).getSingers()+"\n");
            ids.put(i+5,Long.valueOf(i));
        }

        musicList.put(getter.getAccountInfo().getAccountCodeNumber(),ids);
        // 将接下来要执行的指令集存储到ConcurrentHashMap中
        codeMap.put(getter.getAccountInfo().getAccountCodeNumber(),"B,"+params[1]);

        sender.sendGroupMsg(groupMsg,buffer.toString());
    }


    // 分享音乐
    public static void shareMusic(Sender sender,GroupMsg groupMsg,MessageGet messageGet){


        MessageContent msgContent = messageGet.getMsgContent();
        String msg = messageGet.getMsg();
        // 只有当你选择歌曲成功之后才会进行删除
        // 将指令码清除
        String searchMusic = codeMap.get(messageGet.getAccountInfo().getAccountCodeNumber());
        codeMap.remove(messageGet.getAccountInfo().getAccountCodeNumber());

        if (!msg.matches("^[0-9]")){
            sender.sendGroupMsg(groupMsg,"主人,请选择歌曲的序号呢!");
            return;
        }


        HashMap<Integer, Long> ids =
                musicList.get(messageGet.getAccountInfo().getAccountCodeNumber());
        String sharCat = null;

        Integer index = Integer.valueOf(msg);

        Long id = ids.get(index);
        // 网易搜索歌曲
        if(index <= 5) {
            WangYiSongResult musicInfo = null;
            try {
                musicInfo = MusicUtils.getMusicInfo(id);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            if (musicInfo == null || musicInfo.getMusicLink() == null) {
                sender.sendPrivateMsg(messageGet, "对不起,Miku找不到该歌曲,呜呜呜");
                return;
            }


            // 1.1.使用猫猫码来分享音乐
            CatCodeUtil catCodeUtil = CatCodeUtil.getInstance();
            sharCat = catCodeUtil.getStringCodeBuilder("music", false)
                    .key("type")
                    .value("neteaseCloud")
                    .key("musicUrl")
                    .value(musicInfo.getMusicLink())
                    .key("picture")
                    .value(musicInfo.getPicture())
                    .key("title")
                    .value(musicInfo.getSong())
                    .build();
        }
        // QQ音乐来搜索歌曲
        if(index > 5){
            String[] params = searchMusic.split(",");

            QQSongResult qqMusic = null;
            try {
                qqMusic = MusicUtils.getQQMusic(index, params[1]);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            if (qqMusic == null || qqMusic.getData().getUrl() == null) {
                sender.sendPrivateMsg(messageGet, "对不起,Miku找不到该歌曲,呜呜呜");
                return;
            }

            // 1.1.使用猫猫码来分享音乐
            CatCodeUtil catCodeUtil = CatCodeUtil.getInstance();
            sharCat = catCodeUtil.getStringCodeBuilder("music", false)
                    .key("type")
                    .value("QQ")
                    .key("musicUrl")
                    .value(qqMusic.getData().getMusic())
                    .key("picture")
                    .value(qqMusic.getData().getPicture())
                    .key("title")
                    .value(qqMusic.getData().getSong())
                    .build();
        }

        sender.sendGroupMsg(groupMsg,sharCat);
    }


    // 定时提醒的方法
    public static void regularlyRemind(MessageGet getter,GroupMsg groupMsg, Sender sender) {
        String msg = getter.getMsgContent().getMsg();
        String[] remain = msg.split(" ");
        String time = remain[1];
        // 进行格式判断
        if (remain == null || remain.length < 3 ||
                remain.length > 3 ||
                !time.matches("^[0-9]*$") ||
                remain[2].length() > 100) {
            sender.sendPrivateMsg(getter, "您输入格式有问题呢！");
            return;
        }
        // 设置定时任务,每间隔多少时间执行一次
        try {
            ScheduledFuture<?> scheduledFuture = schedule.
                    scheduleAtFixedRate(
                            ()->{
                                sender.sendPrivateMsg(getter,remain[2]);
                                // 这里测试使用秒钟,正式使用使用分钟
                            }, Long.valueOf(time), 5, TimeUnit.MINUTES);
            //使用concurrentHashMap存储
            timeTaskMap.put(getter.getAccountInfo().getAccountCodeNumber(),scheduledFuture);
        }catch(Exception e){
            // 出现异常的话,直接结束任务
            e.printStackTrace();
            schedule.shutdown();
        }

        sender.sendGroupMsg(groupMsg,"(注意:后面加入的定时提醒会覆盖前面的)已经开启定时提醒,取消的话请输入:cancel");
    }


    // 取消定时提醒
    public static void cancelTimeTask(long account,GroupMsg msg, Sender sender) {
        ScheduledFuture<?> timerTask = timeTaskMap.get(account);
        // 取消任务
        timerTask.cancel(true);
        // 防止内存泄露(这里其实也可以给定时任务搞一个虚引用,这样就一定会被GC回收)
        timeTaskMap.remove(account);
        sender.sendGroupMsg(msg,"定时提醒已取消");
    }


    // 获取疫情的信息
    public  static void epidmicGet(Sender sender, GroupMsg msg, MessageGet getter){
        String message = getter.getMsgContent().getMsg();
        // 1.进行消息切割
        String[] params = message.split("^[A-Z] ");

        if(params == null || params.length < 2 || params.length > 2){
            sender.sendPrivateMsg(getter,"主人,您的输入方式有问题呢!");
            return;
        }

        // 获取疫情的信息
        LocationMessage epidemicOfCity = EpidemicHttpUtils.getEpidemicOfCity(params[1]);

        StringBuffer buffer = new StringBuffer();

        buffer.append("=================\n");
        buffer.append("城市:"+epidemicOfCity.getData().getName()+"\n");
        buffer.append("更新时间:"+epidemicOfCity.getData().getTime()+"\n");
        buffer.append("总确诊数:"+epidemicOfCity.getData().getTotal()+"\n");
        buffer.append("疑似确诊:"+epidemicOfCity.getData().getSuspected()+"\n");
        buffer.append("累计死亡:"+epidemicOfCity.getData().getDeath()+"\n");
        buffer.append("累计死亡:"+epidemicOfCity.getData().getDeath()+"\n");
        buffer.append("累计治愈:"+epidemicOfCity.getData().getCure()+"\n");
        buffer.append("累计新增:"+epidemicOfCity.getData().getTotaladd()+"\n");
        buffer.append("现有确诊:"+epidemicOfCity.getData().getEcon()+"\n");
        buffer.append("现有无症状:"+epidemicOfCity.getData().getAsymptom()+"\n");
        buffer.append("=================");

        sender.sendGroupMsg(msg,buffer.toString());
    }


    // 聊天机器人的调用
    public static void chatModeStart(Sender sender,GroupMsg msg,MessageGet getter){
        sender.sendGroupMsg(msg,"聊天模式开启,关闭请输入 exit");
        codeMap.put(getter.getAccountInfo().getAccountCodeNumber(),"D");
    }


    public static void chatMessageGet(Sender sender, GroupMsg msg, MessageGet getter){
        String content = getter.getMsgContent().getMsg();
        String from = getter.getAccountInfo().getAccountCode();
        String fromName = getter.getAccountInfo().getAccountNickname();
        MoliChatRobot chatContent = RobotUtils.getChatContent(content, from, fromName, from, fromName, 2);
        sender.sendGroupMsg(msg,chatContent.getData().get(0).getContent());

        /*ChatRobot chatMessage = ChatRobotUtils.getChatMessage(getter.getMsgContent().getMsg());
        sender.sendGroupMsg(msg,chatMessage.getText())*/;
    }


    // 群管理
    public static void groupManage(Sender sender,
                                   Getter geter,
                                   Setter setter, GroupMsg groupMsg,
                                   MessageGet getter) {
        String msg = getter.getMsgContent().getMsg();
        String atCode = null;

        String[] manageMsg = msg.split(" ");
        if(manageMsg.length != 3){
            sender.sendGroupMsg(groupMsg,"对不起,您输入的格式不对");
            return;
        }


        CatCodeUtil cat = CatCodeUtil.getInstance();
        atCode = cat.getParam(manageMsg[1], "code");
        if(atCode == null && !manageMsg[1].matches("^[a-zA-Z]*$") ){
            sender.sendGroupMsg(groupMsg,"对不起,您输入的格式不对");
            return;
        }


        // 权限判别操作
        boolean flag = false;
        // 当群权限集合没有本群的信息的时候,进行群信息存储
        if(groupPermission.get(groupMsg.getGroupInfo().getGroupCode())==null){
            GroupFullInfo groupInfo = geter.getGroupInfo(groupMsg.getGroupInfo().getGroupCode());
            HashMap<String,Permissions> permissionMap = new HashMap<>();
            // 存储当前群聊的管理员
            for (GroupAdmin admin : groupInfo.getAdmins()) {
                permissionMap.put(admin.getAccountCode(),admin.getPermission());
            }
            // 存储当前群聊的群主
            permissionMap.put(groupInfo.getOwner().getAccountCode(),Permissions.OWNER);
            // 存储当前的群聊的有有权限的人
            groupPermission.put(groupMsg.getGroupInfo().getGroupCode(),permissionMap);
        }

        // 如果此群的群权限内容已经存储了,则比对At的账号的权限与本人的操作权限
        HashMap<String, Permissions> thisGroupPermission
                = groupPermission.get(groupMsg.getGroupInfo().getGroupCode());
        Permissions atPermissions =
                thisGroupPermission.get(getter.getAccountInfo().getAccountCode());

        // 如果是At指令 则获取到At人的账号内容
        if(manageMsg[1].contains("code")){


            Permissions permissions = thisGroupPermission.get(atCode);


            // 当两个都不是null的时候需要比较它们的权限大小
            if(atPermissions !=null && permissions != null){
                flag = atPermissions.isOwner() && permissions.isAdmin();
            }

            flag = (atPermissions != null && permissions == null);

            // 退群指令(当权限达到了之后)
            if("exitGroup".equals(manageMsg[2]) && flag){
                setter.setGroupMemberKick(groupMsg.getGroupInfo().getGroupCode(),atCode,null,false);
            }

            // 禁言指令(当权限达到了之后)
            if(manageMsg[2].matches("^[0-9]*$") && flag){
                setter.setGroupBan(groupMsg.getGroupInfo().getGroupCode(),atCode,Long.valueOf(manageMsg[2]),TimeUnit.MINUTES);
            }

        }


        // 非At指令
        // 加敏感词
        if("addBadWords".equals(manageMsg[1]) && atPermissions != null && manageMsg[2].length() <= 100){
            badWords.add(manageMsg[2]);
            sender.sendGroupMsg(groupMsg,"添加敏感词成功");
        }
        else if("addBadWords".equals(manageMsg[1]) && atPermissions != null && manageMsg[2].length() > 100){
            sender.sendGroupMsg(groupMsg,"对不起,敏感词只能在一百个词以内");
        }

        // 关闭功能
        if(getter.getAccountInfo().getAccountCode().equals(config.getProperty("admin"))&&"close".equals(manageMsg[1])){
            if(!manageMsg[2].matches("^[A-Z]$")){
                sender.sendGroupMsg(groupMsg,"关闭功能的方式不对");
                return;
            }
            Set<Character> groupMenu = closeMenu.get(groupMsg.getGroupInfo().getGroupCode());
            if(groupMenu.isEmpty()){
                HashSet<Character> menu = new HashSet<>();
                menu.add(manageMsg[2].toCharArray()[0]);
                closeMenu.put(groupMsg.getGroupInfo().getGroupCode(),menu);
            }else{
                groupMenu.add(manageMsg[2].toCharArray()[0]);
            }

            sender.sendGroupMsg(groupMsg,"关闭功能成功");
        }

        // 开启功能
        if(getter.getAccountInfo().getAccountCode().equals("3186113904")&&"open".equals(manageMsg[1])){
            if(!manageMsg[2].matches("^[A-Z]$")){
                sender.sendGroupMsg(groupMsg,"开启功能的方式不对");
                return;
            }
            closeMenu.remove(manageMsg[2].toCharArray()[0]);
            sender.sendGroupMsg(groupMsg,"开启功能成功");
        }

    }

    // 群成员加入
    public static void agreeOrdisagreeGroupRequest(GroupAddRequest request,
                                            GroupMsg msg,
                                            MessageGet getter,
                                            Setter setter,Sender sender) {

        Permissions permission = msg.getPermission();


        if(permission.isMember()) {
            return;
        }

        String content = msg.getMsgContent().getMsg();

        if(!content.equals("同意") || content.equals("不同意")) {
            sender.sendGroupMsg(msg,"管理员,是否同意该用户进群");
            return;
        }

        if(content.equals("同意")){
            setter.setGroupAddRequest(request.getFlag(),true,false,"");
        }

        if(content.equals("不同意")){
            setter.setGroupAddRequest(request.getFlag(),false,true,"你太帅了");
        }
        // 清除防止内存泄露
        groupAddRequestMap.remove(msg.getGroupInfo().getGroupCodeNumber());
    }


    // 敏感词检测
    public static void badCheck(String words,GroupMsg msg,Setter setter,
                                MessageGet get,Sender sender){
        for (String badWords:badWords) {
            if(words.contains(badWords)){
                setter.setMsgRecall(get.getFlag());
                sender.sendGroupMsg(msg,"检查到敏感词:"+words);
            }
        }
    }


    // bilibili视频分享
    public static void searchBiliBiliVideo(Sender sender, GroupMsg groupMsg, MessageGet getter) {

        String msg = getter.getMsgContent().getMsg();

        String videoParams = msg.substring(msg.indexOf(" ")+1);

        if(StrUtil.isBlank(videoParams)){
            sender.sendGroupMsg(groupMsg,"输入的格式有问题!");
            return;
        }

        VideoResult video = null;

        try {
            String s = StrUtil.cleanBlank(videoParams);
            video = BiliBiliUtils.getVideo(s);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        if(video.getData() == null || video.getData().size() == 0){
            sender.sendGroupMsg(groupMsg,"对不起没有找到对应的视频");
            return;
        }

        videoMap.put(getter.getAccountInfo().getAccountCode(),video.getData());
        codeMap.put(getter.getAccountInfo().getAccountCodeNumber(),"I");

        StringBuffer buffer = new StringBuffer();
        buffer.append("========= 视频列表 =========\n");
        for (int i = 0; i < video.getData().size() && i <= 5; i++) {
            buffer.append(i+1+"."+video.getData().get(i).getName()+"\n");
        }
        buffer.append("=======================");
        sender.sendGroupMsg(groupMsg,buffer.toString());
    }


    public static void shareBiliBiliVideo(Sender sender, GroupMsg groupMsg, MessageGet getter){
        MessageContent msgContent = getter.getMsgContent();
        String msg = getter.getMsg();
        // 将指令码清除
        codeMap.remove(getter.getAccountInfo().getAccountCodeNumber());

        if (!msg.matches("^[0-9]$")){
            sender.sendGroupMsg(groupMsg,"主人,请选择视频的序号呢!");
            return;
        }

        List<VideoData> videoData = videoMap.get(getter.getAccountInfo().getAccountCode());
        VideoData video = videoData.get(Integer.valueOf(msg)-1);


        CatCodeUtil catCodeUtil = CatCodeUtil.getInstance();
        String sharCat = catCodeUtil.getStringCodeBuilder("share", false)
                .key("title")
                .value(video.getName())
                .key("coverUrl")
                .value(video.getImg())
                .key("url")
                .value(video.getBrief())
                .build();

        sender.sendGroupMsg(groupMsg,sharCat);
    }


    // 每日一图
    public static void sendImage(GroupMsg msg,Sender sender){
        ImageData image = ImageUtils.getImage();
        CatCodeUtil instance = CatCodeUtil.INSTANCE;
        String img = instance.getStringCodeBuilder("image", true)
                .key("file")
                .value(image.getImgurl())
                .key("url")
                .value(image.getImgurl()).build();

        sender.sendGroupMsg(msg,img);
    }

}
